//-----------------------------------------------------------------------------
//
// (c) Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 Xilinx, Inc. All rights reserved.
//
// This file contains confidential and proprietary information
// of Xilinx, Inc. and is protected under U.S. and
// international copyright and other intellectual property
// laws.
//
// DISCLAIMER
// This disclaimer is not a license and does not grant any
// rights to the materials distributed herewith. Except as
// otherwise provided in a valid license issued to you by
// Xilinx, and to the maximum extent permitted by applicable
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
// (2) Xilinx shall not be liable (whether in contract or tort,
// including negligence, or under any other theory of
// liability) for any loss or damage of any kind or nature
// related to, arising under or in connection with these
// materials, including for any direct, or any indirect,
// special, incidental, or consequential loss or damage
// (including loss of data, profits, goodwill, or any type of
// loss or damage suffered as a result of any action brought
// by a third party) even if such damage or loss was
// reasonably foreseeable or Xilinx had been advised of the
// possibility of the same.
//
// CRITICAL APPLICATIONS
// Xilinx products are not designed or intended to be fail-
// safe, or for use in any application requiring fail-safe
// performance, such as life-support or safety devices or
// systems, Class III medical devices, nuclear facilities,
// applications related to the deployment of airbags, or any
// other applications that could lead to death, personal
// injury, or severe property or environmental damage
// (individually and collectively, "Critical
// Applications"). Customer assumes the sole risk and
// liability of any use of Xilinx products in Critical
// Applications, subject only to applicable laws and
// regulations governing limitations on product liability.
//
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
// PART OF THIS FILE AT ALL TIMES.
//
//-----------------------------------------------------------------------------
// Project    : Spartan-6 Integrated Block for PCI Express
// File       : PIO_EP.v
// Description: Endpoint Programmed I/O module.
//
//-----------------------------------------------------------------------------

`timescale 1ns/1ns

module PIO_EP(
  // Common
  input              clk,
  input              rst_n,

   // AXIS TX
  input              s_axis_tx_tready,
  output  [31:0]     s_axis_tx_tdata,
  output  [3:0]      s_axis_tx_tkeep,
  output             s_axis_tx_tlast,
  output             s_axis_tx_tvalid,
  output             tx_src_dsc,

  //AXIS RX
  input  [31:0]      m_axis_rx_tdata,
  input  [3:0]       m_axis_rx_tkeep,
  input              m_axis_rx_tlast,
  input              m_axis_rx_tvalid,
  output             m_axis_rx_tready,
  input    [21:0]    m_axis_rx_tuser,

  // Turn-off signaling
  output            req_compl_o,
  output            compl_done_o,

  // Configuration
  input [15:0]      cfg_completer_id,
  input             cfg_bus_mstr_enable,

  // AD
  input             ad_clk
  );

  // Local wires

  wire  [10:0]      rd_addr;
  wire  [3:0]       rd_be;
  wire  [31:0]      rd_data;

  wire  [10:0]      wr_addr;
  wire  [7:0]       wr_be;
  wire  [31:0]      wr_data;
  wire              wr_en;
  wire              wr_busy;

  wire  [10:0]      internal_wr_addr;
  wire  [31:0]      internal_wr_data;
  wire              internal_wr_en;

  wire              req_compl;
  wire              req_compl_with_data;
  wire              compl_done;

  wire  [2:0]       req_tc;
  wire              req_td;
  wire              req_ep;
  wire  [1:0]       req_attr;
  wire  [9:0]       req_len;
  wire  [15:0]      req_rid;
  wire  [7:0]       req_tag;
  wire  [7:0]       req_be;
  wire  [12:0]      req_addr;


  wire              rd_data_en;

  wire              up_wr_req;
  wire  [29:0]      up_pc_mem_addr;
  wire  [31:0]              up_wr_data;
  wire                      up_wr_data_rdy;
  wire                      up_wr_done;


  wire [31:0]       ad_data;
  wire              ad_data_valid;
  wire              ad_acquisition_en;

  //
  // ENDPOINT MEMORY : 8KB memory aperture implemented in FPGA BlockRAM(*)
  //

  up_wr up_wr_inst(
      .clk( clk ),
      .rst_n( rst_n ),
      .wr_addr_i( wr_addr ),
      .wr_be_i( wr_be ),
      .wr_data_i( wr_data ),
      .wr_en_i( wr_en ),
      .internal_wr_addr_o( internal_wr_addr ),
      .internal_wr_data_o( internal_wr_data ),
      .internal_wr_en_o(   internal_wr_en   ),

      .ad_clk( ad_clk ),    // For AD
      .ad_data_i ( ad_data ),
      .ad_data_valid_i( ad_data_valid ),
      .ad_acquisition_en_o ( ad_acquisition_en ),

      .up_wr_req_o( up_wr_req ), // For TX engine
      .up_wr_start_i ( up_wr_start ),
      .up_pc_mem_addr_o( up_pc_mem_addr ),
      .up_wr_data_o( up_wr_data ),
      .up_wr_data_rdy_o ( up_wr_data_rdy ),
      .up_wr_done_i( up_wr_done )
  );
  PIO_EP_MEM_ACCESS EP_MEM (
    .clk(clk),                           // I
    .rst_n(rst_n),                       // I

    // Read Port
    .rd_addr_i(rd_addr),                 // I [10:0]
    .rd_be_i(rd_be),                     // I [3:0]
    .rd_data_o(rd_data),                 // O [31:0]

    // Write Port
    .wr_addr_i(wr_addr),                 // I [10:0]
    .wr_be_i(wr_be),                     // I [7:0]
    .wr_data_i(wr_data),                 // I [31:0]
    .wr_en_i(wr_en),                     // I
    .wr_busy_o(wr_busy),                 // O

    .rd_data_en( rd_data_en ),

    .internal_wr_addr_i( internal_wr_addr ),
    .internal_wr_data_i( internal_wr_data ),
    .internal_wr_en_i(   internal_wr_en   )

    );

    AD_DUMMY inst(
        .clk( ad_clk ),
        .rst( !rst_n ),
        .ad_data_o( ad_data ),
        .ad_data_valid_o ( ad_data_valid ),
        .ad_acquisition_en_i( ad_acquisition_en )
    );


  //
  // Local-Link Receive Controller
  //
  PIO_32_RX_ENGINE EP_RX (
    .clk(clk),                              // I
    .rst_n(rst_n),                          // I

    // AXIS RX
    .m_axis_rx_tdata( m_axis_rx_tdata ),    // I
    .m_axis_rx_tkeep( m_axis_rx_tkeep ),    // I
    .m_axis_rx_tlast( m_axis_rx_tlast ),    // I
    .m_axis_rx_tvalid( m_axis_rx_tvalid ),  // I
    .m_axis_rx_tready( m_axis_rx_tready ),  // O
    .m_axis_rx_tuser ( m_axis_rx_tuser ),   // I

    // Handshake with Tx engine
    .req_compl_o(req_compl),             // O
    .req_compl_with_data_o(req_compl_with_data), // O
    .compl_done_i(compl_done),           // I

    .req_tc_o(req_tc),                   // O [2:0]
    .req_td_o(req_td),                   // O
    .req_ep_o(req_ep),                   // O
    .req_attr_o(req_attr),               // O [1:0]
    .req_len_o(req_len),                 // O [9:0]
    .req_rid_o(req_rid),                 // O [15:0]
    .req_tag_o(req_tag),                 // O [7:0]
    .req_be_o(req_be),                   // O [7:0]
    .req_addr_o(req_addr),               // O [12:0]

    // Memory Write Port
    .wr_addr_o(wr_addr),                 // O [10:0]
    .wr_be_o(wr_be),                     // O [7:0]
    .wr_data_o(wr_data),                 // O [31:0]
    .wr_en_o(wr_en),                     // O
    .wr_busy_i(wr_busy)                  // I
    );

  //
  // Local-Link Transmit Controller
  //
  PIO_32_TX_ENGINE EP_TX (
    .clk(clk),                          // I
    .rst_n(rst_n),                      // I

   // AXIS Tx
    .s_axis_tx_tready( s_axis_tx_tready ),      // I
    .s_axis_tx_tdata( s_axis_tx_tdata ),        // O
    .s_axis_tx_tkeep( s_axis_tx_tkeep ),        // O
    .s_axis_tx_tlast( s_axis_tx_tlast ),        // O
    .s_axis_tx_tvalid( s_axis_tx_tvalid ),      // O
    .tx_src_dsc( tx_src_dsc ),                  // O

    // Handshake with Rx engine
    .req_compl_i(req_compl),            // I
    .req_compl_with_data_i(req_compl_with_data), // I
    .compl_done_o(compl_done),          // 0

    .req_tc_i(req_tc),                  // I [2:0]
    .req_td_i(req_td),                  // I
    .req_ep_i(req_ep),                  // I
    .req_attr_i(req_attr),              // I [1:0]
    .req_len_i(req_len),                // I [9:0]
    .req_rid_i(req_rid),                // I [15:0]
    .req_tag_i(req_tag),                // I [7:0]
    .req_be_i(req_be),                  // I [7:0]
    .req_addr_i(req_addr),              // I [12:0]

    // Read Port
    .rd_addr_o(rd_addr),                // O [10:0]
    .rd_be_o(rd_be),                    // O [3:0]
    .rd_data_i(rd_data),                // I [31:0]

    .completer_id_i(cfg_completer_id),  // I [15:0]
    .cfg_bus_mstr_enable_i(cfg_bus_mstr_enable), // I

    .rd_data_en( rd_data_en),
    .up_wr_req_i( up_wr_req ),
    .up_wr_start_o( up_wr_start ),
    .up_pc_mem_addr_i( up_pc_mem_addr ),
    .up_wr_data_i( up_wr_data ),
    .up_wr_data_rdy_i( up_wr_data_rdy ),
    .up_wr_done_o ( up_wr_done )


    );

  assign req_compl_o  = req_compl;
  assign compl_done_o = compl_done;

endmodule // PIO_EP

